<?php
namespace app\admin\core;
use app\admin\model\Module as ModuleModel;
use think\Db;

/**
 * Class Install
 * @package app\admin\core
 * 用来安装模块，获取模块信息之类的操作
 */
class Module {
    const FILTER_MODULE = [
        'admin',
        'common',
        'extra',
    ];
    const PATH_MODULE_CONFIG = 'info';
    const FILE_MODULE_CONFIG = 'info/info.php';     // 相对模块目录，config文件的路径
    const FILE_MODULE_INSTALL = 'info/install.sql';
    const FILE_MODULE_UNINSTALL = 'info/uninstall.sql';
    const FILE_MODULE_CLEAR_DATA = 'info/cleardata.sql';
    const FILE_MODULE_STATUS = 'info/status.json';
    private static $moduleList = null;      // 不要直接使用，用getModuleList来获取
    public function isInstall($moduleName) {
        $list = $this->getModuleList();
        return $list[$moduleName]['status']['installed'];
    }
    public function install($moduleName) {
        if(!$this->isInstall($moduleName)) {
            $this->execSqlFile($this->getInstallFile($moduleName));
            $status['installed'] = true;
            $this->setStatus($moduleName,$status);
            return true;
        }else {
            return false;
        }
    }

    public function clearData($moduleName) {
        if($this->isInstall($moduleName)) {
            $this->execSqlFile($this->getClearDataFile($moduleName));
            return true;
        }else {
            return false;
        }
    }

    public function uninstall($moduleName) {
        if($this->isInstall($moduleName)) {
            $this->execSqlFile($this->getUninstallFile($moduleName));
            $status['installed'] = false;
            $this->setStatus($moduleName,$status);
            return true;
        }else {
            return false;
        }
    }

    public function getConfig($moduleName) {
        return require($this->getConfigFile($moduleName));
    }
    public function getInstalledModuleList() {
        $data = [];
        foreach ($this->getModuleList() as $name => $module ) {
            if($module['status']['installed'] == true) {
                $data[$name] = $module;
            }
        }
        return $data;
    }
    public function getUninstallModuleList() {

    }
    public function getModuleList() {
        if($this::$moduleList === null) {
            $modules = $this->readdir(APP_PATH , $this::FILTER_MODULE);

            foreach ($modules as $module) {
                if(file_exists($this->getPath($module,$this::PATH_MODULE_CONFIG))) {
                    $this::$moduleList[$module]['name'] = $module;
                    $statusFile = $this->getStatusFile($module);
                    if(file_exists($statusFile)) {
                        $json = json_decode(file_get_contents($statusFile),true);
                        $this::$moduleList[$module]['status'] = $json;
                    }else {
                        $this::$moduleList[$module]['status']['installed'] = false;
                    }
                }
            }
        }
        return $this::$moduleList;
    }
    private function getConfigFile($moduleName) {
        return $this->getPath($moduleName,$this::FILE_MODULE_CONFIG);
    }
    private function getInstallFile($moduleName) {
        return $this->getPath($moduleName,$this::FILE_MODULE_INSTALL);
    }
    private function getUninstallFile($moduleName) {
        return $this->getPath($moduleName,$this::FILE_MODULE_UNINSTALL);
    }
    private function getClearDataFile($moduleName) {
        return $this->getPath($moduleName,$this::FILE_MODULE_CLEAR_DATA);
    }
    private function getStatusFile($moduleName) {
        return $this->getPath($moduleName,$this::FILE_MODULE_STATUS);
    }
    private function getPath($moduleName,$relativePath) {
        return APP_PATH . DS . $moduleName . DS . $relativePath;
    }

    /**
     * 注意，返回的数组，只有目录，没有文件
     * @param $dir
     * @param array $filter
     * @return array
     */
    private function readdir($dir,$filter = []) {
        $filter = array_merge($filter,['.','..']);
        $cur = getcwd();
        chdir($dir);
        $handle = opendir($dir);
        $ret = [];
        while (false !== ($file = readdir($handle))) {
            if(is_dir(($file)) && !in_array($file,$filter))
                $ret[] = $file;
        }
        closedir($handle);
        chdir($cur);
        return $ret;
    }
    private function execSqlFile($filename) {
        if(file_exists($filename)) {
            $sql = file_get_contents($filename);
            $this->execSqlStr($sql);
        }
    }

    private function execSqlStr($str) {
        if($str) {
            $arr = explode(";",$str);

            foreach ($arr as $val) {
                $val = trim($val);
                if($val == '') {
                    continue;
                }
                Db::execute($val . ';');
            }
        }

    }

    private function setStatus($moduleName,$jsonArray) {
        $file = $this->getStatusFile($moduleName);
        file_put_contents($file,json_encode($jsonArray));
    }
}